package web_filter

import (
	"gitee.com/kristas/booting-go/framework/core/ioc/bean_factory"
	"gitee.com/kristas/booting-go/framework/web"
	"net/http"
	"regexp"
	"sort"
)

var (
	filters []web.Filter
)

func NewFilterChain(w http.ResponseWriter, r *http.Request, service web.Service) error {
	var head, curr web.FilterChain
	for i := range filters {
		f := filters[i]
		if !isPatternMatched(f.UrlPatterns(), r.RequestURI) {
			continue
		}
		if head == nil {
			head = newFilterChain(f, service)
			curr = head
		} else {
			curr.SetNext(newFilterChain(f, service))
			curr = curr.GetNext()
		}
	}
	if head == nil {
		return service()
	}
	return head.GetFilter().DoFilter(w, r, head)
}

func isPatternMatched(patterns []string, uri string) (matched bool) {
	for _, pattern := range patterns {
		pattern = "^" + pattern
		matched, _ = regexp.MatchString(pattern, uri)
		if matched {
			break
		}
	}
	return
}

func InitFilters(trace func(order int, filter web.Filter)) {
	filters = getFilters()
	sort.Slice(filters, func(i, j int) bool {
		return filters[i].Order() < filters[j].Order()
	})
	for i := range filters {
		trace(i+1, filters[i])
	}
}

func getFilters() (filters []web.Filter) {
	values := bean_factory.GetApplicationContext().GetBeansByInterface(new(web.Filter))
	for i := range values {
		filters = append(filters, values[i].(web.Filter))
	}
	return
}
